﻿using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using DevExpress.XtraEditors;
using ScanAPIHelper;


namespace ACTest.FS80Test
{
	public partial class MainForm : XtraForm
	{

		#region Constant

		const int FTR_ERROR_EMPTY_FRAME = 4306;
		const int FTR_ERROR_MOVABLE_FINGER = 0x20000001;
		const int FTR_ERROR_NO_FRAME = 0x20000002;
		const int FTR_ERROR_USER_CANCELED = 0x20000003;
		const int FTR_ERROR_HARDWARE_INCOMPATIBLE = 0x20000004;
		const int FTR_ERROR_FIRMWARE_INCOMPATIBLE = 0x20000005;
		const int FTR_ERROR_INVALID_AUTHORIZATION_CODE = 0x20000006;

		/* Other return codes are Windows-compatible */
		const int ERROR_NO_MORE_ITEMS = 259;                // ERROR_NO_MORE_ITEMS
		const int ERROR_NOT_ENOUGH_MEMORY = 8;              // ERROR_NOT_ENOUGH_MEMORY
		const int ERROR_NO_SYSTEM_RESOURCES = 1450;         // ERROR_NO_SYSTEM_RESOURCES
		const int ERROR_TIMEOUT = 1460;                     // ERROR_TIMEOUT
		const int ERROR_NOT_READY = 21;                     // ERROR_NOT_READY
		const int ERROR_BAD_CONFIGURATION = 1610;           // ERROR_BAD_CONFIGURATION
		const int ERROR_INVALID_PARAMETER = 87;             // ERROR_INVALID_PARAMETER
		const int ERROR_CALL_NOT_IMPLEMENTED = 120;         // ERROR_CALL_NOT_IMPLEMENTED
		const int ERROR_NOT_SUPPORTED = 50;                 // ERROR_NOT_SUPPORTED
		const int ERROR_WRITE_PROTECT = 19;                 // ERROR_WRITE_PROTECT
		const int ERROR_MESSAGE_EXCEEDS_MAX_SIZE = 4336;    // ERROR_MESSAGE_EXCEEDS_MAX_SIZE

		[DllImport("gdi32.dll")]
		private static extern IntPtr CreateDIBitmap(IntPtr hdc, [In] ref BitmapInfoHeader lpbmih,
													uint fdwInit, byte[] lpbInit, byte[] lpbmi,
													uint fuUsage);
		/* constants for CreateDIBitmap */
		const int CBM_INIT = 0x04;   /* initialize bitmap */

		/* DIB color table identifiers */

		const int DIB_RGB_COLORS = 0; /* color table in RGBs */
		const int DIB_PAL_COLORS = 1; /* color table in palette indices */
		const int BI_RGB = 0;
		const int BI_RLE8 = 1;
		const int BI_RLE4 = 2;
		const int BI_BITFIELDS = 3;
		const int BI_JPEG = 4;
		const int BI_PNG = 5;

		#endregion

		#region Field

		private Device _device;
		private bool _cancelOperation;
		private byte[] _frame;

		#endregion

		#region Constructor

		public MainForm()
		{
			InitializeComponent();
		}

		#endregion

		#region Event

		private void MainForm_Load(object sender, EventArgs e)
		{
			Device.BaseInterface = 0;
			_device = new Device();
			_device.Open();
			GetFrame();

			if (_frame != null && _frame.Length != 0)
			{
				var size = _device.ImageSize;
				Graphics gr = pictureBox.CreateGraphics();
				Bitmap hBitmap = CreateBitmap(gr.GetHdc(), size, _frame);
				hBitmap.RotateFlip(RotateFlipType.Rotate180FlipX);
				pictureBox.Image = hBitmap;
			}
		}

		#endregion

		#region Private Method

		private void GetFrame()
		{
			int lastErrorCode = 0;
			bool continueOperation = true;
			do
			{
				while (!_device.IsFingerPresent && !_cancelOperation)
				{
					if (lastErrorCode != _device.LastErrorCode)
					{
						lastErrorCode = _device.LastErrorCode;
						switch (lastErrorCode)
						{
							case 0:
								break;
							case FTR_ERROR_EMPTY_FRAME:
								XtraMessageBox.Show("Put finger to the scanner");
								break;
							case FTR_ERROR_MOVABLE_FINGER:
								XtraMessageBox.Show("There is no stable fingerprint image on the device.");
								break;
							case FTR_ERROR_NO_FRAME:
								XtraMessageBox.Show("Fake finger was detected");
								break;
							case FTR_ERROR_HARDWARE_INCOMPATIBLE:
							case FTR_ERROR_FIRMWARE_INCOMPATIBLE:
								XtraMessageBox.Show("The device does not support the requested feature");
								break;
							default:
								var msg = String.Format("Unknown error #{0}", lastErrorCode);
								XtraMessageBox.Show(msg);
								break;
						}
					}
					Thread.Sleep(0);
				}
				if (!_cancelOperation)
				{
					try
					{
						_frame = _device.GetFrame();
						continueOperation = false;
					}
					catch (ScanAPIException)
					{
						lastErrorCode = _device.LastErrorCode;
						switch (lastErrorCode)
						{
							case 0:
								break;
							case FTR_ERROR_EMPTY_FRAME:
								XtraMessageBox.Show("Put finger to the scanner");
								break;
							case FTR_ERROR_MOVABLE_FINGER:
								XtraMessageBox.Show("There is no stable fingerprint image on the device.");
								break;
							case FTR_ERROR_NO_FRAME:
								XtraMessageBox.Show("Fake finger was detected");
								break;
							case FTR_ERROR_HARDWARE_INCOMPATIBLE:
							case FTR_ERROR_FIRMWARE_INCOMPATIBLE:
								XtraMessageBox.Show("The device does not support the requested feature");
								break;
							default:
								var msg = String.Format("Unknown error #{0}", lastErrorCode);
								XtraMessageBox.Show(msg);
								break;
						}
					}
				}
				else
				{
					break;
				}
			} while (continueOperation);
		}

		private Bitmap CreateBitmap(IntPtr hdc, Size bmpSize, byte[] data)
		{
			var mem = new System.IO.MemoryStream();
			var bw = new System.IO.BinaryWriter(mem);
			//BITMAPINFO bmpInfo = new BITMAPINFO();
			var bmiHeader = new BitmapInfoHeader();
			bmiHeader.biSize = 40;
			bmiHeader.biWidth = bmpSize.Width;
			bmiHeader.biHeight = bmpSize.Height;
			bmiHeader.biPlanes = 1;
			bmiHeader.biBitCount = 8;
			bmiHeader.biCompression = BI_RGB;
			bw.Write(bmiHeader.biSize);
			bw.Write(bmiHeader.biWidth);
			bw.Write(bmiHeader.biHeight);
			bw.Write(bmiHeader.biPlanes);
			bw.Write(bmiHeader.biBitCount);
			bw.Write(bmiHeader.biCompression);
			bw.Write(bmiHeader.biSizeImage);
			bw.Write(bmiHeader.biXPelsPerMeter);
			bw.Write(bmiHeader.biYPelsPerMeter);
			bw.Write(bmiHeader.biClrUsed);
			bw.Write(bmiHeader.biClrImportant);

			for (int i = 0; i < 256; i++)
			{
				bw.Write((byte)i);
				bw.Write((byte)i);
				bw.Write((byte)i);
				bw.Write((byte)0);
			}

		
			var hBitmap = data != null ? CreateDIBitmap(hdc, ref bmiHeader, CBM_INIT, data, mem.ToArray(), DIB_RGB_COLORS) : CreateDIBitmap(hdc, ref bmiHeader, 0, null, mem.ToArray(), DIB_RGB_COLORS);
			return Image.FromHbitmap(hBitmap);
		}

		#endregion

	}
}